/* 
 * File:   PDSFile.h
 * Author: gip
 *
 * Created on August 8, 2010, 5:45 AM
 */

#ifndef _PDSFILE_H
#define	_PDSFILE_H

using namespace std;
#include <string>
#include "UniApoFile.h"
#include "Section.h"
#include "ParsedDataString.h"
#include "MAPFile.h"
#include "SDSFile.h"
#include <stdlib.h>

class PDSFile : public UniApoFile {
public:
    //constructor, destructor and copy constructor
    PDSFile();
    PDSFile(const PDSFile& orig);
    virtual ~PDSFile();

    //Adding entry to PDS
    void addEntry(ParsedDataString PDS, int i);


    //adding statements in bulk from any text file
    void bulk(string path);

    //Build file from object and Save to disk.
    void buildFile();

    //Print file contents to screen
    void print();
    //Load file from given path in to this object.
    bool loadFile();

    //Give this option a name
    void name(string n);

    // vector<ParsedDataString>& getData();

    void setSDS(SDSFile& SDS);
    //Operations in regards to MAPfile
    void setMAP(MAPFile& MAP);

    SDSFile& getSDS();
    //Operations in regards to MAPfile
    MAPFile& getMAP();

    void getSQL();
    void getValSQL(int entryNo);
    void getDisplaySQL(int entryNo);
    void getPKSQL(int entryNo);
    int sqlstatus(int entryNo);

    void printResult(int entryNo);


private:
    int last;
    map<int, ParsedDataString> PDSsection;
    MAPFile sourceMAP;
    SDSFile sourceSDS;
    bool setStructures();
    //Reads the DRT section and finds the identifier of the DRT and ST
    //in the database.
    bool setRealVal();
};

PDSFile::PDSFile() {

}

PDSFile::PDSFile(const PDSFile& orig) {
    PDSsection = orig.PDSsection;
    sourceMAP = orig.sourceMAP;
    sourceSDS = orig.sourceSDS;
    filename = orig.filename;
    extension = orig.extension;
    path = orig.path;
}

PDSFile::~PDSFile() {
}

void PDSFile::addEntry(ParsedDataString PDS, int i) {
    PDSsection.insert(pair<int, ParsedDataString > (i, PDS));
}

void PDSFile::buildFile() {
    ofstream newPDSFile;
    newPDSFile.open(path.c_str());
    newPDSFile << "filename: " << filename.c_str() << "\n";
    newPDSFile << "extension: " << extension.c_str() << "\n";
    newPDSFile << "SDS: " << sourceSDS.getFilename() << "\n";
    newPDSFile << "MAP: " << sourceMAP.getFilename() << "\n\n";
    newPDSFile << ".PDS" << "\n";

    map<int, ParsedDataString>::iterator i;
    for (i = PDSsection.begin(); i != PDSsection.end(); ++i) {
        newPDSFile << ".RESULT\n" << (*i).first << "\n";
        newPDSFile << sourceSDS.getDataString((*i).first) << "\n";
        newPDSFile << (*i).second << endl;
        newPDSFile << ".END_RESULT\n";
    }
    newPDSFile << ".END_PDS";
    newPDSFile.close();
}

bool PDSFile::loadFile() {

    ifstream PDSFile(path.c_str());
    string line;
    int i;
    if (PDSFile.is_open()) {

        //first process header
        getline(PDSFile, line); //first line is mapname
        line = line.substr(10, line.size()); //ommit "filename:"
        filename = line.substr(0, line.size() - 4);
        extension = "PDS";
        getline(PDSFile, line); // skip extension line

        getline(PDSFile, line); //then the SDS filename
        line = line.substr(4, line.size()); //ommit "SDS"
        //Remove trailing whitespaces
        while (line[0] == ' ')
            line.erase(0, 1);
        //ommit extension

        i = line.find(".SDS");
        line = line.substr(0, i);
        sourceSDS.name(line);


        //Get MAP filename
        getline(PDSFile, line);

        line = line.substr(4, line.size()); //ommit "MAP"

        while (line[0] == ' ')
            line.erase(0, 1);

        //ommit extension
        i = line.find(".MAP");
        line = line.substr(0, i);
        sourceMAP.name(line);
        //Load SCB and DBS contents in container
        //TO-DO: loadfile with boolean and check if they exist

        sourceMAP.loadFile();

        sourceSDS.loadFile();

        while (line != ".PDS") {
            getline(PDSFile, line);

        }
        while (line != ".END_PDS") {
            getline(PDSFile, line);

            if (line == ".RESULT") {
                getline(PDSFile, line);
                ParsedDataString PDS;
                int entryNo;
                stringstream ss(line);
                ss >> entryNo;
                getline(PDSFile, line);
                PDS.setDS(line);

                getline(PDSFile, line);
                while (line != ".END_RESULT") {
                    //Load entry in errormap
                    //cout << line << endl;
                    PDS.loadContent(line);
                    getline(PDSFile, line);
                }
                this->addEntry(PDS, entryNo);
            }

        }
        this->getSQL();
        return true;
    }
    else return false;
}

void PDSFile::name(string n) {
    filename = n;
    extension = "PDS";
    this->setPath();

}

void PDSFile::setSDS(SDSFile& SDS) {
    sourceSDS = SDS;
}

void PDSFile::setMAP(MAPFile& MAP) {
    sourceMAP = MAP;
}

SDSFile& PDSFile::getSDS() {
    return sourceSDS;
}

MAPFile& PDSFile::getMAP() {
    return sourceMAP;
}

void PDSFile::print() {
    map<int, ParsedDataString>::iterator i;
    int counter = 1;
    for (i = PDSsection.begin(); i != PDSsection.end(); ++i) {
        ParsedDataString pdsel = (*i).second;
        cout << "Entry number: " << counter << " " << pdsel.getDS();
        cout << "(" << pdsel.getOutputCode() << ")" << endl;
        cout << endl;
        //cout << pdsel.getStructure() << endl << endl;

        counter++;
    }
}

void PDSFile::getSQL() {
    this->setStructures();
}

bool PDSFile::setStructures() {

    map<int, ParsedDataString>::iterator i;
    for (i = PDSsection.begin(); i != PDSsection.end(); ++i) {
        (*i).second.setStructure();
        vector<DMLStatement> psql;
        //vector<DMLStatement>::iterator ipsql;

        psql = sourceMAP.getPSQL((*i).second.getStructure().getString());
        (*i).second.setSQLvect(psql);
    }
    return true;
}

void PDSFile::getValSQL(int entryNo) {
    map<int, ParsedDataString>::iterator i;
    i = PDSsection.find(entryNo);
    if (i != PDSsection.end()) {
        (*i).second.printVal();
    }
}

void PDSFile::getDisplaySQL(int entryNo) {
    map<int, ParsedDataString>::iterator i;
    i = PDSsection.find(entryNo);
    if (i != PDSsection.end()) {
        (*i).second.printDisplay();
    }
}

void PDSFile::getPKSQL(int entryNo) {
    map<int, ParsedDataString>::iterator i;
    i = PDSsection.find(entryNo);
    if (i != PDSsection.end()) {
        (*i).second.printPK();
    }
}

int PDSFile::sqlstatus(int entryNo) {
    map<int, ParsedDataString>::iterator i;
    i = PDSsection.find(entryNo);
    if (i != PDSsection.end()) {
        return (*i).second.getOutputCode();
    }

}

void PDSFile::printResult(int entryNo) {
    map<int, ParsedDataString>::iterator i;
    i = PDSsection.find(entryNo);
    if (i != PDSsection.end()) {
        cout << (*i).second.getStructure() << endl;
        cout << "with values:" << endl;
        (*i).second.print();
    }
}
#endif	/* _PDSFILE_H */

